#include <iostream>
#include <opencv2/opencv.hpp>
#include <string> // 需要包含 string 库
#include <vector>

// 可调节参数配置
struct {
    int         gaussianKernelSize = 9;        // 高斯核尺寸（必须为奇数）
    double      binaryThreshold = 200;         // 二值化阈值 (0-255)
    int         morphologyKernelSize = 5;      // 形态学操作核尺寸
    double      minContourArea = 100;          // 最小轮廓面积过滤阈值
    std::string outputFilename = "result.jpg"; // 结果保存路径
} circle_date_t;

int main(int argc, char **argv)
{

    // 1. 定义输入路径
    const std::string input_path = "../images/circle001.jpg"; // 原图路径

    // 2. 解析文件名（自动提取前缀和后缀）
    size_t last_slash = input_path.find_last_of("/"); // 定位最后一个斜杠
    size_t last_dot = input_path.find_last_of(".");   // 定位最后一个点号

    // 提取目录路径、文件名前缀、扩展名
    std::string dir_path = input_path.substr(0, last_slash + 1); // 目录路径 (如 "../images/")
    std::string file_prefix = input_path.substr(last_slash + 1, last_dot - last_slash - 1); // 文件名 (如 "sumu001")
    std::string file_ext = input_path.substr(last_dot);                                     // 扩展名 (如 ".jpg")

    // 3. 读取原图
    cv::Mat image = cv::imread(input_path);
    if (image.empty())
    {
        std::cerr << "Error: Could not open image file: " << input_path << std::endl;
        return -1;
    }
    // 获取分辨率信息
    const int         width = image.cols;
    const int         height = image.rows;
    const std::string resolution_info = " Resolution: " + std::to_string(width) + "x" + std::to_string(height);
    // 核心公式：内存大小 = 图像宽 × 高 × 通道数 × 数据类型字节数。OpenCV 快捷方法：image.total() * image.elemSize()
    size_t memory_bytes = image.total() * image.elemSize(); // 核心公式
    std::cout << "[Success] Image loaded: " << input_path << resolution_info << " ";
    std::cout << "memory_bytes: " << memory_bytes << "bytes" << std::endl;
    // 4. 转换为灰度图
    cv::Mat gray_image;
    cv::cvtColor(image, gray_image, cv::COLOR_BGR2GRAY);

    // 5. 灰度图预处理
    // 5.1 高斯模糊降噪
    GaussianBlur(gray_image, gray_image, cv::Size(circle_date_t.gaussianKernelSize, circle_date_t.gaussianKernelSize),
                 2, 2);

    // 5.2 二值化处理
    cv::Mat binary_image;
    threshold(gray_image, binary_image, circle_date_t.binaryThreshold, 255, cv::THRESH_BINARY);

    // 5.3 形态学操作闭合小孔洞
    cv::Mat kernel = cv::getStructuringElement(
        cv::MORPH_RECT, cv::Size(circle_date_t.morphologyKernelSize, circle_date_t.morphologyKernelSize));
    morphologyEx(binary_image, binary_image, cv::MORPH_CLOSE, kernel);

    // 6. 识别二值化图像中的圆形区域
    // 6.1 轮廓检测
    std::vector<std::vector<cv::Point>> contours;
    findContours(binary_image, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

    // 6.2 圆心检测与可视化
    cv::Mat                  result_image = image.clone(); // 创建一个与原图大小相同的图像，用于绘制结果
    std::vector<cv::Point2f> detectedCenters;
    int i = 0;
    for (const auto &contour : contours)
    {
        // 过滤小面积噪声
        const double area = cv::contourArea(contour);
        if (area < circle_date_t.minContourArea)
            continue;

        // 计算最小包围圆
        cv::Point2f center;
        float       radius;
        cv::minEnclosingCircle(contour, center, radius);

        // 存储结果
        detectedCenters.push_back(center);

        // 可视化标注
        const cv::Scalar green(0, 255, 0); // BGR颜色空间
        const cv::Scalar red(0, 0, 255);

        cv::circle(result_image, center, 3, green, -1);   // 中心点
        cv::circle(result_image, center, radius, red, 2); // 外接圆
        i++;
        if(i%2 == 0)
        {
        cv::putText(result_image, "(" + std::to_string((int)center.x) + "," + std::to_string((int)center.y) + ")",
                    center + cv::Point2f(-20, -30), cv::FONT_HERSHEY_SIMPLEX, 0.5, green, 1);
        }
        else
        {
            cv::putText(result_image, "(" + std::to_string((int)center.x) + "," + std::to_string((int)center.y) + ")",
                    center + cv::Point2f(20, 30), cv::FONT_HERSHEY_SIMPLEX, 0.5, green, 1);
        }
    }
    // 7. 生成结果图片输出路径
    circle_date_t.outputFilename = file_prefix + "_circle" + file_ext; // 组合新路径 (如 "sumu001_gray.jpg")
    if (!cv::imwrite(circle_date_t.outputFilename, result_image))
    {
        std::cerr << "错误：结果保存失败！" << std::endl;
        return EXIT_FAILURE;
    }
    std::cout << "[Success] result image saved to: " << circle_date_t.outputFilename << std::endl;

    // 8. 控制台输出检测结果
    std::cout << "\n检测到 " << detectedCenters.size() << " 个高亮区域：" << std::endl;
    for (size_t i = 0; i < detectedCenters.size(); ++i)
    {
        const auto &center = detectedCenters[i];
        std::cout << "circle " << i + 1 << ": X = " << center.x << " Y = " << center.y << std::endl;
    }
    std::cout << "[Success] 检测完成！" << std::endl;

    return 0;
}